package com.xiaohui.redis.util;

import com.xiaohui.redis.exception.ShareRedisException;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Component
public class RedisShareLockUtil {

    @Resource
    private RedisUtil redisUtil;

    private static final Long TIME_OUT = 1000L;

    /**
     * 加锁
     * @param key
     * @param requestId
     * @param expire
     * @return
     */
    public boolean lock(String key, String requestId, long expire) {
        // 参数校验
        if(StringUtils.isBlank(key) || StringUtils.isBlank(requestId) || expire <= 0){
            throw new ShareRedisException("参数错误");
        }
        // 自旋
        long currentTime = System.currentTimeMillis();
        long maxTime = currentTime + TIME_OUT;
        boolean result = false;
        while (currentTime < maxTime) {
            result = redisUtil.setNx(key, requestId, expire, TimeUnit.MILLISECONDS);
            if (result) {
                return result;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            currentTime = System.currentTimeMillis();
        }
        return result;
    }

    /**
     * 解锁
     * @param key
     * @param requestId
     */
    public void unlock(String key, String requestId) {
        if(StringUtils.isBlank(key) || StringUtils.isBlank(requestId)){
            throw new ShareRedisException("参数错误");
        }
        String value = redisUtil.get(key);
        if(requestId.equals(value)){
            redisUtil.del(key);
        }
    }

    /**
     * 尝试加锁
     * @param key
     * @param requestId
     * @param expire
     * @return
     */
    public boolean tryLock(String key, String requestId, long expire) {
        if (StringUtils.isBlank(key) || StringUtils.isBlank(requestId) || expire <= 0){
            throw new ShareRedisException("参数错误");
        }
        return redisUtil.setNx(key, requestId, expire, TimeUnit.MILLISECONDS);
    }
}
